import { LocalFile, LocalFileService, TableData } from "./LocalFileService";
import { portal as saveLoading } from "src/components/Project/modals/SaveLoading.vue";
import download from "../download";
import { chooseFile, formatTime, uint8ArrayToString } from "../common";
import xlsx from "xlsx";
import { portal as OpenLoading } from "components/Project/modals/OpenLoading.vue";
import {
  MofModelRepositoryHelper,
  SysMLUtilHelper
} from "src/api/sysml-imports";
import { storage } from "src/util/common";

export class LocalFileBrowser implements LocalFile {
  getInitProject() {
    return LocalFileService.getInitProject();
  }
  async saveProject(project: Project): Promise<any> {
    return saveLoading.popup({
      time: 2,
      saveFn: async () => {
        project.config.updateDate = formatTime(Date.now());
        const blob = LocalFileService.parseProjectToBlob(project);
        download({
          filename: project.config.projectName + ".md3",
          content: blob
        });
        project.ui.modified = false;
      }
    });
  }
  async saveAsProjectXML(project: Project): Promise<any> {
    return saveLoading.popup({
      time: 2,
      saveFn: async () => {
        project.config.updateDate = formatTime(Date.now());
        const blob = LocalFileService.parseProjectToBlob(project);
        const Parser = require("fast-xml-parser").j2xParser;
        const blobObj = JSON.parse(blob);
        blobObj.model = blobObj.model.replace(/</g, '_&lt;_').replace(/>/g, '_&gt;_');
        const nodeStatus = {};
        Object.keys( blobObj.onlineConfig.nodeStatus).forEach(key => {
          nodeStatus['k' + key] =  blobObj.onlineConfig.nodeStatus[key];
        });
        blobObj.onlineConfig.nodeStatus = nodeStatus;

        const options = {
          arrayMode: true,
          //// attributeNamePrefix: "",
          ignoreAttributes: false,
          allowBooleanAttributes: true,
          parseNodeValue: true,
          parseAttributeValue: true
        };
        //// delete blobObj.model;
        const parser = new Parser(options);
        const result = parser.parse({ xml: blobObj });

        download({
          filename: project.config.projectName + ".xml",
          content: result
        });
        project.ui.modified = false;
      }
    });
  }

  async updateProject(project: Project): Promise<any> {
    const projectId = project.config.id;
    app.proxy.projects.delete(projectId);
    //// SysMLUtilHelper.removePoolById(projectId);
    MofModelRepositoryHelper.removePool(projectId);
    project.config.updateDate = formatTime(Date.now());
    console.log("加载模型:", project.metadata.sysml.model.model);

    let newProject: Project = null;
    await OpenLoading.popup({
      time: 1,
      msg: "读取中...",
      Fn: async () => {
        const blob = LocalFileService.parseProjectToBlob(project);
        newProject = await LocalFileService.loadProjectData(blob);
        console.log("project", project);
      }
    });
    return Promise.resolve(project);
  }

  saveAsProject(project: Project): Promise<Project> {
    return this.saveProject(project);
  }
  async openProject(filePath?: string): Promise<any> {
    const result = await chooseFile(".md3");
    if (!result) return;
    const { data, name } = result;
    let project: Project;
    await saveLoading.popup({
      time: 1,
      msg: "读取中...",
      saveFn: async () => {
        project = await LocalFileService.loadProjectData(data);
        project.config.projectName = name.replace(".md3", "");
        //// project.config.projectPath = path.dirname(filePath);
      }
    });
    return project;
  }

  async importProject(filePath?: string): Promise<any> {
    const result = await chooseFile(".md3");
    if (!result) return;
    const { data, name } = result;
    let project: Project;
    await saveLoading.popup({
      time: 1,
      msg: "读取中...",
      saveFn: async () => {
        project = await LocalFileService.parseProjectData(data);
        project.config.projectName = name.replace(".md3", "");
      }
    });
    return project;
  }
  async importProjectXML(filePath?: string): Promise<any> {
    const blob = await chooseFile(".xml");
    if (!blob) return;
    const { data, name } = blob;

    const parser = require('fast-xml-parser');
    const options = {
      ignoreAttributes: false,
      allowBooleanAttributes: true,
      parseNodeValue: true,
      parseAttributeValue: true
    };
    const uintData = new Uint8Array(data);
    const str =  uint8ArrayToString(uintData);
    console.log('str', str);
    let result = parser.parse(str, options);
    console.log('result', result);

    result = result.xml;
    console.log(result.model);
    result.model = result.model.replace(/_&lt;_/g, '<').replace(/_&gt;_/g, '>');
    const nodeStatus = {};
    Object.keys(result.onlineConfig.nodeStatus).forEach(key => {
      const key2 = key.substring(1);
      nodeStatus[key2] = result.onlineConfig.nodeStatus[key];
    });
    result.onlineConfig.nodeStatus = nodeStatus;
    console.log('导入后的result', result);
    const model = result.model.text;

    if (typeof result.config.rootIds === 'string'){
      const arr = [];
      arr.push(result.config.rootIds);
      result.config.rootIds = arr;
    }
    if (result.config && result.config.projectName) result.config.projectName = result.config.projectName.toString();
    if (result.config && result.config.version) result.config.version = result.config.version.toString();
    if (result.onlineConfig && result.onlineConfig.version) result.onlineConfig.version = result.onlineConfig.version.toString();
    if (result.onlineConfig && result.onlineConfig.privileges) result.onlineConfig.privileges = {};

    let project: Project;
    await saveLoading.popup({
      time: 1,
      msg: "读取中...",
      saveFn: async () => {
        project = await LocalFileService.parseProjectData(JSON.stringify(result));
        project.config.projectName = name.replace(".xml", "");
      }
    });
    return project;
  }
  switchToProject(project: Project) {
    return LocalFileService.switchToProject(project);
  }
  async importProfile(project: Project, filePaths: string[]): Promise<any> {
    return LocalFileService.importProfile(project, filePaths);
  }

  async beforeOpenExcelAndReqif(type) {
    const typeConfig = {
      fileName: '',
      typeName: ''
    };
    switch (type) {
      case 'excel':
        typeConfig.fileName = '需求表导入模板.xlsx';
        typeConfig.typeName = 'Excel';
        break;
      case 'reqif':
        typeConfig.fileName = '需求表导入模板.reqif';
        typeConfig.typeName = 'Reqif';
        break;
      default:
        break;
    }
    let result = {
      checked: false
    };
    if (!storage.get(`notTip-importTable-${type}`)) {
      result = await app.$Confirm
        .popup({
          title: "提示",
          subTitle: `导入${typeConfig.typeName}`,
          content: `系统只读取${typeConfig.typeName}的id, name, text字段。`,
          subContent: "导入后将生成新的需求表和需求放在独立的包内。",
          showCheckbox: true,
          checkboxText: "不再提示",
          status: "warn",
          cancelText: "取消",
        })
        .catch(e => {
          e && console.error(e);
          return false;
        });
      if (result.checked) {
        storage.set(`notTip-importTable-${type}`, true);
      }
    }
    return result;
  }

  async openExcel(type) {
    const result = await this.beforeOpenExcelAndReqif(type);
    if (!result) return Promise.reject();
    const data = await chooseFile(".xlsx");
    return new Promise((rs, rj) => {
      if (data) {
        rs(data);
      } else {
        rj();
      }
    });
  }

  async openReqif(type) {
    const result = await this.beforeOpenExcelAndReqif(type);
    if (!result) return Promise.reject();
    const data = await chooseFile(".reqif");
    data.data = Buffer.from(data.data);
    return new Promise((rs, rj) => {
      if (data) {
        rs(data);
      } else {
        rj();
      }
    });
  }

  exportRequirementTableExcel(
    tableData: TableData,
    name: string,
    farmatter: any
  ): Promise<any> {
    return new Promise((rs, rj) => {
      const jsonData = [];
      this.travelRow(tableData.visibleRows, row => {
        const result = {};
        row.cells.forEach(cell => {
          const value = cell.value;
          let name = cell.name;
          if (farmatter && farmatter[name] !== undefined) {
            name = farmatter[name];
          }
          if (Array.isArray(value)) {
            result[name] = value.map(val => val.name).join("\r\n");
          } else if (value instanceof Object) {
            result[name] = value.name;
          } else {
            result[name] = value;
          }
        });
        jsonData.push(result);
      });
      let ss = xlsx.utils.json_to_sheet(jsonData); //// 通过工具将json转表对象
      //// let keys = Object.keys(ss).sort(); //// 排序 [需要注意，必须从A1开始]

      //// let ref = keys[1] + ":" + keys[keys.length - 1]; //// 这个是定义一个字符串 也就是表的范围[A1:C5]

      let workbook = {
        //// 定义操作文档
        SheetNames: ["Sheet1"], //// 定义表明
        Sheets: {
          Sheet1: Object.assign({}, ss) //// 表对象[注意表明]
        }
      };
      console.log(jsonData, "jsonData");
      xlsx.writeFile(workbook, name + ".xlsx"); //// 将数据写入文件
      rs("导出成功");
    });
  }
  exportRequirementTableReqif(
    tableData: TableData,
    name: string
  ): Promise<any> {
    return new Promise((rs, rj) => {});
  }
  /**
   *
   * @param project
   */
  saveProjectSilence(project: Project): Promise<any> {
    project.ui.modified = false;
    LocalFileService.updateRecentProjects(project);
    return Promise.resolve(true);
  }
  travelRow(rows: Array<UmlShape>, fn: (row: UmlShape) => void) {
    rows.forEach(row => {
      fn(row);
      if (row.children) {
        this.travelRow(row.children, fn);
      }
    });
  }

  exportProfile(): Promise<any> {
    return Promise.resolve(undefined);
  }

  openProfile(): Promise<any> {
    app.$messageBox.warn({ text: '暂未提供此功能' });
    return Promise.reject();
  }

  reloadProject(): Promise<any> {
    return new Promise((res, rej) => {});
  }

  downLoadFile({ filename, content, contentType, selectPath }) {
    download({ filename: filename + ".md3t", content: content, contentType });
  }

  exportPackage(graphNode: GraphNode): Promise<any> {
    return Promise.resolve(undefined);
  }
}
